package hjw.com.config;


import hjw.com.util.JwtUtil;
import hjw.com.util.PackJsn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>Project:Academic - JwtAuthenFilter
 * <p>Description: 每一次业务请求（具体增删改查） 验证 Token， 创建正常 Authentication (账号， 权限）
 * @author IvanWei玮 -- maste
 * @version 1.0
 * @DataTime 2025/1/20 14:13
 * @since 1.8
 */
public class JwtAuthenFilter extends BasicAuthenticationFilter {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**认证管理器 authenticationManager*/
    public JwtAuthenFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws IOException, ServletException {

        //除了 api/login2 外， 都会到这里
        logger.debug("业务请求:" + request.getServletPath());
        logger.debug("授权过滤器- 获取 Token，创建 认证成功的用户对象");
        String bearer_token = request.getHeader("Authorization");

        logger.info("Bearer=" + bearer_token);
        //放行所有访问public的请求
        if (request.getRequestURI().startsWith("/api/public")){
            logger.info("所有访问 /api/public 以下的服务都给它放行");
            chain.doFilter(request, response);
            //直接放行， 到一个过滤器
            return;
        }
        if (bearer_token == null || (!bearer_token.startsWith("Bearer"))) {
            logger.info("第一种情形, 没有 Token, 可能访问 /api/public");
            logger.info("第一种情形: 无需 认证对象（账号， 权限）， 直接放行");
            chain.doFilter(request, response);
            //直接放行， 到一个过滤器
            return;
        }
        String token = bearer_token.substring(7);
        //Bearer (6+1)
        logger.debug("token=" + token);
        logger.info("第二种情形： 有Token, 校验 Token 签名， 有效期");
        if (!JwtUtil.isValid(token)) {
            // Token 过期， 要不签名不合法
            logger.info("第二种情形： 有Token, 但是校验失败");
            logger.info("Token 要不要放行， 需要根据自己的需要");
            response.setStatus(403);
            response.setContentType("application/json;charset=utf-8");
            String ret = PackJsn.pack(403, "登录过期！", "");
            response.getWriter().write(ret);
            response.flushBuffer();
            return;
        }
        logger.info("第三种情形： 合法Token， 创建 Authentication 对象， 成功登录的对象");
        logger.info("从 Token 获取 账号， 角色权限， 去创建一个Authentication 成功登录对象");
        String username = JwtUtil.getUsername(token);
        List<String> roles = JwtUtil.getRoles(token);
        List<SimpleGrantedAuthority> lst = new ArrayList<>();
        for(String s : roles) {
            lst.add( new SimpleGrantedAuthority(s));
        }
        User user= new User(username, "", lst);
        logger.info("造一个成功登录的用户对象，必须有账号和权限");
        UsernamePasswordAuthenticationToken authention =
                new UsernamePasswordAuthenticationToken(user, null, lst);
        logger.info("把成功登录的伪造的对象， " +
                "放在 类似 Session 的结构 SecurityContextHolder");
        SecurityContextHolder.getContext().setAuthentication(authention);
        // 每次业务请求， 把成功登录的用户信息放在 SecurityContextHolder， 表示当前登录成功了
        chain.doFilter(request, response);
    }
}

//控制层如何获取当前登录的用户信息
//SecurityContextHolder.getContext().getAuthentication().getPrincipal();
